package org.rkuk.kasutil.designPatternTools 
{
	import flash.utils.getQualifiedClassName;
	/**
	 * 用于生成抽象类和抽象方法，在非法创建抽象类实例和调用抽象方法时，抛出异常帮助检测错误。
	 * @author rkuk
	 */
	public final class AbstractTool
	{
		/**
		 * 用于创建抽象类.
		 * 在需要被定义为抽象类的构造函数中加入此方法后，如果创建该抽象类的实例，则会抛出异常。
		 * @param	object				传入this对象
		 * @param	abstractClass		被定义的抽象类本身
		 * @param	message				自定义抛出异常的message
		 * @throws	Error				如果创建抽象类的实例，则会抛出异常
		 * @example 如果要将MyAbstractClass定义为抽象类，则在MyAbstractClass的构造函数中加入如下语句：
		 * <listing>
		 * AbstractTool.makeAbstractClass(this,MyAbstractClass);
		 * </listing>
		 */
		public static function makeAbstractClass(object:Object,abstractClass:Class,message:String=null):void
		{
			if (object.constructor === abstractClass)
			{
				if (message == null)
					message = getClassErrorMessage(getQualifiedClassName(object));
					
				throw new Error(message);
			}
		}
		
		/**
		 * 用于创建抽象方法.
		 * 在需要被定义为抽象方法的函数体中加入此方法后，如果该抽象方法被调用，则会抛出异常。
		 * <p/>注：如果子类中override该抽象方法，则不能再用super调用基类的抽象方法。
		 * @param	object				抽象方法中的this
		 * @param	methodName			抽象方法的名称
		 * @param	message				自定义抛出异常的message
		 * @return	返回类型设置为*是为了在有返回值的抽象方法中，可以将makeAbstractMethod语句直接放在return后，简化代码。
		 * @throws	Error				如果调用抽象方法，则会抛出异常
		 * @example	如果要将MyAbstractClass.theAbstractMethod定义为抽象方法，则在theAbstractMethod的函数体中加入如下语句：
		 * <listing>
		 * AbstractTool.makeAbstractMethod(this,"theAbstractMethod");
		 * </listing>
		 */
		public static function makeAbstractMethod(object:Object, abstractMethodName:String,message:String=null):*
		{
			var className:String = getQualifiedClassName(object);
			
			if (message == null)
				message = getMethodErrorMessage(abstractMethodName,className);
				
			throw new Error(message);
			return null;
		}
		
		/**
		 * @private
		 */
		public function AbstractTool() 
		{
			makeAbstractClass(this, AbstractTool);
		}
		
		private static function getClassErrorMessage(abstractClassName:String):String
		{
			return "Can not create instance of abstract class : " + abstractClassName;
		}
		
		private static function getMethodErrorMessage(abstractMethodName:String,abstractClassName:String):String
		{
			return "Abstract method \"" + abstractMethodName + "\" isn't implemented in class : " + abstractClassName;	
		}
	}
}